<template>
  <div class="xml-formatter-tool">
    <div class="tool-header">
      <h1>XML格式化</h1>
      <p>格式化XML数据</p>
    </div>

    <div class="tool-container">
      <el-row :gutter="20">
        <!-- 格式化主体 -->
        <el-col :span="16">
          <div class="formatter-section">
            <!-- XML输入 -->
            <div class="xml-input">
              <h3>XML输入</h3>
              <div class="input-actions">
                <el-button @click="pasteXML" size="small">
                  <el-icon><DocumentCopy /></el-icon>
                  粘贴XML
                </el-button>
                <el-button @click="clearXML" size="small">
                  清空
                </el-button>
                <el-button @click="loadSample" size="small">
                  加载示例
                </el-button>
              </div>
              <el-input
                v-model="inputXML"
                type="textarea"
                :rows="12"
                placeholder="请输入要格式化的XML数据..."
                class="xml-textarea"
              />
            </div>
            
            <!-- 格式化选项 -->
            <div class="format-options">
              <h3>格式化选项</h3>
              <div class="options-grid">
                <div class="option-group">
                  <label>缩进类型：</label>
                  <el-select v-model="formatOptions.indentType" size="small">
                    <el-option label="空格" value="space" />
                    <el-option label="制表符" value="tab" />
                  </el-select>
                </div>
                <div class="option-group">
                  <label>缩进大小：</label>
                  <el-select v-model="formatOptions.indentSize" size="small">
                    <el-option label="2" :value="2" />
                    <el-option label="4" :value="4" />
                    <el-option label="8" :value="8" />
                  </el-select>
                </div>
                <div class="option-group">
                  <label>行长度：</label>
                  <el-input-number v-model="formatOptions.lineLength" :min="40" :max="200" size="small" />
                </div>
                <div class="option-group">
                  <label>属性排序：</label>
                  <el-switch v-model="formatOptions.sortAttributes" size="small" />
                </div>
                <div class="option-group">
                  <label>移除空行：</label>
                  <el-switch v-model="formatOptions.removeEmptyLines" size="small" />
                </div>
                <div class="option-group">
                  <label>压缩模式：</label>
                  <el-switch v-model="formatOptions.compress" size="small" />
                </div>
              </div>
            </div>
            
            <!-- 格式化按钮 -->
            <div class="format-actions">
              <el-button @click="formatXML" type="primary" size="large" :loading="isFormatting" :disabled="!inputXML.trim()">
                <el-icon><Edit /></el-icon>
                格式化XML
              </el-button>
              <el-button @click="validateXML" size="large" :disabled="!inputXML.trim()">
                <el-icon><Search /></el-icon>
                验证XML
              </el-button>
              <el-button @click="copyResult" size="large" :disabled="!formattedXML">
                <el-icon><DocumentCopy /></el-icon>
                复制结果
              </el-button>
              <el-button @click="downloadResult" size="large" :disabled="!formattedXML">
                <el-icon><Download /></el-icon>
                下载文件
              </el-button>
            </div>
            
            <!-- 格式化结果 -->
            <div class="format-result" v-if="formattedXML">
              <h3>格式化结果</h3>
              <div class="result-info">
                <div class="info-item">
                  <span class="info-label">原始行数：</span>
                  <span class="info-value">{{ originalLines }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">格式化后行数：</span>
                  <span class="info-value">{{ formattedLines }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">字符数：</span>
                  <span class="info-value">{{ formattedXML.length }}</span>
                </div>
                <div class="info-item">
                  <span class="info-label">文件大小：</span>
                  <span class="info-value">{{ fileSize }}</span>
                </div>
              </div>
              <el-input
                v-model="formattedXML"
                type="textarea"
                :rows="12"
                readonly
                class="xml-textarea"
              />
            </div>
            
            <!-- XML验证结果 -->
            <div class="validation-result" v-if="validationResult">
              <h3>验证结果</h3>
              <div class="validation-status" :class="validationResult.valid ? 'valid' : 'invalid'">
                <el-icon v-if="validationResult.valid"><Check /></el-icon>
                <el-icon v-else><Close /></el-icon>
                {{ validationResult.valid ? 'XML格式正确' : 'XML格式错误' }}
              </div>
              <div v-if="!validationResult.valid && validationResult.errors.length > 0" class="error-list">
                <h4>错误信息：</h4>
                <div class="error-item" v-for="(error, index) in validationResult.errors" :key="index">
                  <div class="error-message">{{ error.message }}</div>
                  <div class="error-line">行 {{ error.line }}，列 {{ error.column }}</div>
                </div>
              </div>
            </div>
            
            <!-- 格式化历史 -->
            <div class="format-history">
              <h3>格式化历史</h3>
              <div class="history-list">
                <div 
                  v-for="(item, index) in formatHistory" 
                  :key="index"
                  class="history-item"
                  @click="loadFromHistory(item)"
                >
                  <div class="history-info">
                    <span class="history-lines">{{ item.lines }} 行</span>
                    <span class="history-size">{{ item.size }}</span>
                    <span class="history-time">{{ item.time }}</span>
                  </div>
                </div>
                <div v-if="formatHistory.length === 0" class="empty-history">
                  暂无格式化历史
                </div>
              </div>
            </div>
          </div>
        </el-col>

        <!-- 工具和说明 -->
        <el-col :span="8">
          <div class="tools-section">
            <div class="section-header">
              <h3>XML示例</h3>
            </div>
            
            <div class="xml-samples">
              <div 
                v-for="sample in xmlSamples" 
                :key="sample.name"
                class="sample-item"
                @click="loadSampleXML(sample)"
              >
                <div class="sample-name">{{ sample.name }}</div>
                <div class="sample-description">{{ sample.description }}</div>
              </div>
            </div>
          </div>
          
          <div class="help-section">
            <el-card>
              <template #header>
                <div class="card-header">
                  <span>使用说明</span>
                </div>
              </template>
              
              <div class="help-content">
                <h4>格式化功能：</h4>
                <ul>
                  <li><strong>缩进格式化：</strong> 自动添加缩进</li>
                  <li><strong>属性排序：</strong> 按字母顺序排列属性</li>
                  <li><strong>空行处理：</strong> 移除多余空行</li>
                  <li><strong>压缩模式：</strong> 生成紧凑格式</li>
                </ul>
                
                <h4>验证功能：</h4>
                <ul>
                  <li><strong>语法检查：</strong> 验证XML语法</li>
                  <li><strong>结构检查：</strong> 检查标签配对</li>
                  <li><strong>错误定位：</strong> 显示错误位置</li>
                </ul>
                
                <h4>注意事项：</h4>
                <div class="warning">
                  <p>⚠️ 确保XML语法正确</p>
                  <p>⚠️ 大型文件可能影响性能</p>
                  <p>⚠️ 格式化会改变原始结构</p>
                </div>
              </div>
            </el-card>
          </div>
        </el-col>
      </el-row>
    </div>
  </div>
</template>

<script setup>
import { ref, computed } from 'vue'
import { ElMessage } from 'element-plus'
import { DocumentCopy, Edit, Search, Download, Check, Close } from '@element-plus/icons-vue'

const inputXML = ref('')
const formattedXML = ref('')
const isFormatting = ref(false)
const validationResult = ref(null)
const formatHistory = ref([])

const formatOptions = ref({
  indentType: 'space',
  indentSize: 2,
  lineLength: 80,
  sortAttributes: false,
  removeEmptyLines: true,
  compress: false
})

const xmlSamples = [
  {
    name: '简单XML',
    description: '基本的XML结构',
    xml: '<root><name>John</name><age>30</age></root>'
  },
  {
    name: '带属性的XML',
    description: '包含属性的XML',
    xml: '<person id="1" name="John" age="30"><email>john@example.com</email><phone>123-456-7890</phone></person>'
  },
  {
    name: '嵌套XML',
    description: '多层嵌套的XML',
    xml: '<company><department name="IT"><employee id="1"><name>John</name><position>Developer</position></employee><employee id="2"><name>Jane</name><position>Designer</position></employee></department></company>'
  },
  {
    name: 'CDATA示例',
    description: '包含CDATA的XML',
    xml: '<data><![CDATA[This is CDATA content with special characters: <>&]]></data>'
  },
  {
    name: '注释示例',
    description: '包含注释的XML',
    xml: '<!-- 这是注释 --><root><!-- 另一个注释 --><item>内容</item></root>'
  }
]

const originalLines = computed(() => {
  return inputXML.value ? inputXML.value.split('\n').length : 0
})

const formattedLines = computed(() => {
  return formattedXML.value ? formattedXML.value.split('\n').length : 0
})

const fileSize = computed(() => {
  if (!formattedXML.value) return '0 B'
  const bytes = new Blob([formattedXML.value]).size
  if (bytes < 1024) return `${bytes} B`
  if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB`
  return `${(bytes / (1024 * 1024)).toFixed(1)} MB`
})

const pasteXML = async () => {
  try {
    const text = await navigator.clipboard.readText()
    inputXML.value = text
    ElMessage.success('XML已粘贴')
  } catch (error) {
    ElMessage.error('无法访问剪贴板')
  }
}

const clearXML = () => {
  inputXML.value = ''
  formattedXML.value = ''
  validationResult.value = null
  ElMessage.info('XML已清空')
}

const loadSample = () => {
  inputXML.value = xmlSamples[0].xml
  ElMessage.success('示例XML已加载')
}

const loadSampleXML = (sample) => {
  inputXML.value = sample.xml
  ElMessage.success(`已加载：${sample.name}`)
}

const formatXML = async () => {
  if (!inputXML.value.trim()) {
    ElMessage.warning('请输入要格式化的XML数据')
    return
  }
  
  isFormatting.value = true
  
  try {
    // 模拟格式化过程
    await new Promise(resolve => setTimeout(resolve, 1000))
    
    let formatted = inputXML.value.trim()
    
    if (formatOptions.value.compress) {
      // 压缩模式：移除所有空白和换行
      formatted = formatted.replace(/>\s+</g, '><').replace(/\s+/g, ' ').trim()
    } else {
      // 格式化模式
      formatted = formatXMLString(formatted)
    }
    
    formattedXML.value = formatted
    
    // 添加到历史
    addToHistory()
    
    ElMessage.success('XML格式化完成')
    
  } catch (error) {
    ElMessage.error('格式化失败：' + error.message)
  } finally {
    isFormatting.value = false
  }
}

const formatXMLString = (xml) => {
  // 简单的XML格式化逻辑
  let formatted = xml
  const indent = formatOptions.value.indentType === 'tab' ? '\t' : ' '.repeat(formatOptions.value.indentSize)
  let level = 0
  
  // 处理标签
  formatted = formatted
    .replace(/></g, '>\n<')
    .split('\n')
    .map(line => {
      line = line.trim()
      if (!line) return ''
      
      if (line.startsWith('</')) {
        level--
      }
      
      const indentedLine = indent.repeat(Math.max(0, level)) + line
      
      if (line.startsWith('<') && !line.startsWith('</') && !line.endsWith('/>')) {
        level++
      }
      
      return indentedLine
    })
    .filter(line => line || !formatOptions.value.removeEmptyLines)
    .join('\n')
  
  return formatted
}

const validateXML = async () => {
  if (!inputXML.value.trim()) {
    ElMessage.warning('请输入要验证的XML数据')
    return
  }
  
  try {
    // 模拟验证过程
    await new Promise(resolve => setTimeout(resolve, 500))
    
    // 简单的XML验证逻辑
    const errors = []
    const lines = inputXML.value.split('\n')
    
    // 检查基本语法
    const xml = inputXML.value.trim()
    
    // 检查根标签
    if (!xml.startsWith('<') || !xml.endsWith('>')) {
      errors.push({
        message: 'XML必须以标签开始和结束',
        line: 1,
        column: 1
      })
    }
    
    // 检查标签配对
    const openTags = xml.match(/<[^\/][^>]*>/g) || []
    const closeTags = xml.match(/<\/[^>]*>/g) || []
    
    if (openTags.length !== closeTags.length) {
      errors.push({
        message: '标签不配对，请检查开始和结束标签',
        line: 1,
        column: 1
      })
    }
    
    // 检查特殊字符
    if (xml.includes('&') && !xml.includes('&amp;') && !xml.includes('&lt;') && !xml.includes('&gt;')) {
      errors.push({
        message: '包含未转义的特殊字符',
        line: 1,
        column: xml.indexOf('&') + 1
      })
    }
    
    validationResult.value = {
      valid: errors.length === 0,
      errors: errors
    }
    
    if (errors.length === 0) {
      ElMessage.success('XML格式验证通过')
    } else {
      ElMessage.error(`发现 ${errors.length} 个错误`)
    }
    
  } catch (error) {
    ElMessage.error('验证失败：' + error.message)
  }
}

const copyResult = async () => {
  try {
    await navigator.clipboard.writeText(formattedXML.value)
    ElMessage.success('结果已复制到剪贴板')
  } catch (error) {
    ElMessage.error('复制失败')
  }
}

const downloadResult = () => {
  const filename = 'formatted.xml'
  
  const blob = new Blob([formattedXML.value], { type: 'text/xml' })
  const url = URL.createObjectURL(blob)
  const a = document.createElement('a')
  a.href = url
  a.download = filename
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  URL.revokeObjectURL(url)
  
  ElMessage.success('文件已下载')
}

const addToHistory = () => {
  const historyItem = {
    lines: formattedLines.value,
    size: fileSize.value,
    time: new Date().toLocaleString('zh-CN')
  }
  
  formatHistory.value.unshift(historyItem)
  
  // 限制历史记录数量
  if (formatHistory.value.length > 20) {
    formatHistory.value = formatHistory.value.slice(0, 20)
  }
}

const loadFromHistory = (item) => {
  ElMessage.success(`已加载：${item.lines} 行格式化历史`)
}
</script>

<style scoped>
.xml-formatter-tool {
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px;
}

.tool-header {
  text-align: center;
  margin-bottom: 40px;
}

.tool-header h1 {
  font-size: 2.5rem;
  color: #333;
  margin-bottom: 10px;
}

.tool-header p {
  color: #666;
  font-size: 1.1rem;
}

.tool-container {
  margin-bottom: 40px;
}

.formatter-section,
.tools-section {
  background: white;
  border-radius: 12px;
  padding: 24px;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
  border: 1px solid #f0f0f0;
  height: 100%;
}

.xml-input,
.format-options,
.format-actions,
.format-result,
.validation-result,
.format-history {
  margin-bottom: 30px;
}

.xml-input h3,
.format-options h3,
.format-result h3,
.validation-result h3,
.format-history h3 {
  color: #333;
  margin-bottom: 20px;
  font-size: 1.3rem;
}

.input-actions {
  display: flex;
  gap: 10px;
  margin-bottom: 15px;
}

.xml-textarea {
  font-family: 'Courier New', monospace;
  font-size: 14px;
  line-height: 1.5;
}

.format-options {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 20px;
  border: 1px solid #e9ecef;
}

.options-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 15px;
}

.option-group {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.option-group label {
  font-weight: 500;
  color: #666;
}

.format-actions {
  display: flex;
  gap: 15px;
  flex-wrap: wrap;
}

.result-info {
  display: flex;
  gap: 20px;
  margin-bottom: 15px;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.info-item {
  display: flex;
  flex-direction: column;
  align-items: center;
}

.info-label {
  font-size: 0.9rem;
  color: #666;
  margin-bottom: 5px;
}

.info-value {
  font-size: 1.1rem;
  font-weight: bold;
  color: #333;
}

.validation-result {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 20px;
  border: 1px solid #e9ecef;
}

.validation-status {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 1.1rem;
  font-weight: bold;
  margin-bottom: 15px;
}

.validation-status.valid {
  color: #28a745;
}

.validation-status.invalid {
  color: #dc3545;
}

.error-list {
  margin-top: 15px;
}

.error-list h4 {
  color: #333;
  margin-bottom: 10px;
  font-size: 1.1rem;
}

.error-item {
  background: #f8d7da;
  border-radius: 6px;
  padding: 10px;
  margin-bottom: 8px;
  border-left: 4px solid #dc3545;
}

.error-message {
  color: #721c24;
  font-weight: bold;
  margin-bottom: 5px;
}

.error-line {
  color: #856404;
  font-size: 0.9rem;
}

.history-list {
  max-height: 300px;
  overflow-y: auto;
}

.history-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  margin-bottom: 10px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid #e9ecef;
}

.history-item:hover {
  background: #e9ecef;
  transform: translateY(-1px);
}

.history-info {
  display: flex;
  gap: 15px;
  font-size: 0.9rem;
  color: #666;
}

.history-lines {
  color: #667eea;
  font-weight: 500;
}

.history-size {
  color: #28a745;
  font-weight: 500;
}

.history-time {
  color: #999;
}

.empty-history {
  text-align: center;
  color: #999;
  padding: 40px 0;
  font-style: italic;
}

.section-header {
  margin-bottom: 20px;
}

.section-header h3 {
  color: #333;
  margin: 0;
  font-size: 1.3rem;
}

.xml-samples {
  display: flex;
  flex-direction: column;
  gap: 10px;
}

.sample-item {
  background: #f8f9fa;
  border-radius: 8px;
  padding: 15px;
  cursor: pointer;
  transition: all 0.2s ease;
  border: 1px solid #e9ecef;
}

.sample-item:hover {
  background: #e9ecef;
  transform: translateY(-2px);
}

.sample-name {
  font-size: 1rem;
  font-weight: bold;
  color: #333;
  margin-bottom: 5px;
}

.sample-description {
  font-size: 0.9rem;
  color: #666;
}

.help-section {
  margin-top: 20px;
}

.card-header {
  font-weight: bold;
  color: #333;
}

.help-content h4 {
  color: #333;
  margin: 20px 0 10px 0;
  font-size: 1.1rem;
}

.help-content ul {
  color: #666;
  padding-left: 20px;
  margin-bottom: 15px;
}

.help-content li {
  margin-bottom: 5px;
}

.warning {
  background: #fff3cd;
  padding: 15px;
  border-radius: 8px;
  border-left: 4px solid #ffc107;
  margin: 15px 0;
}

.warning p {
  margin: 5px 0;
  color: #856404;
}

@media (max-width: 768px) {
  .tool-header h1 {
    font-size: 2rem;
  }
  
  .options-grid {
    grid-template-columns: 1fr;
  }
  
  .format-actions {
    flex-direction: column;
  }
  
  .result-info {
    flex-direction: column;
    gap: 10px;
  }
  
  .history-info {
    flex-direction: column;
    gap: 5px;
  }
}
</style>